package com.jiahao.quickshot.View;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;

import com.jiahao.quickshot.model.Point;
import com.jiahao.quickshot.multitouch.MoveGestureDetector;

/**
 * Created by hp on 2016/9/23 11:42.
 */

public class ZoomImageView extends ImageView implements
        View.OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener {
    private static final String TAG = ZoomImageView.class.getSimpleName();
    /**
     * 缩放比例的最大最小值
     */
    public static final float SCALE_MAX = 4.0f;
    public static final float SCALE_MIN = 0.5f;
    /**
     * 初始化时的缩放比例，如果图片宽或高大于屏幕，此值将小于0
     */
    private static final float initScale = 1.0f;
    /**
     * 用于存放矩阵的9个值
     */
    private final float[] matrixValues = new float[9];
    private final Matrix mMatrix = new Matrix();

    private boolean once = true;

    /**
     * 缩放的手势检测
     */
    private ScaleGestureDetector mScaleDetector = null;
    private float mScaleFactor = 1.f;

    private float mFocusX;
    private float mFocusY;
    private Point centerPoint;
    private boolean DrawableWidthBiggerThanHeight ;

    public ZoomImageView(Context context) {
        this(context, null);
    }

    public ZoomImageView(Context context, AttributeSet attrs){
        super(context, attrs);
        super.setScaleType(ScaleType.MATRIX);
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
//        mMoveDetector = new MoveGestureDetector(context, new MoveListener());
        this.setOnTouchListener(this);
    }

    /**
     * 根据当前图片的Matrix获得图片的范围
     * @return
     */
    private RectF getMatrixRectF() {
        Matrix matrix = mMatrix;
        RectF rect = new RectF();
        Drawable d = getDrawable();
        if (null != d) {
            rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
            matrix.mapRect(rect);
        }
        return rect;
    }

/*    private RectF getMaxRectF() {
        int width = getWidth();
        int height = getHeight();
        RectF rect = new RectF();
        rect.set(0, 0, width, height);
        return rect;
    }*/

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
//        mMoveDetector.onTouchEvent(event);
        boolean retVal = mScaleDetector.onTouchEvent(event);
        retVal = mScaleDetector.onTouchEvent(event) || retVal;
        return retVal || super.onTouchEvent(event);
    }


    /**
     * 获得当前的缩放比例
     *
     * @return
     */
    public final float getScale()
    {
        mMatrix.getValues(matrixValues);
//        Log.d(TAG, "getScale: MSCALE_X=" + matrixValues[Matrix.MSCALE_X]);
        return matrixValues[Matrix.MSCALE_X];
    }

    @Override
    protected void onAttachedToWindow()
    {
        super.onAttachedToWindow();
        getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onDetachedFromWindow()
    {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    @Override
    public void onGlobalLayout()
    {
        if (once) {
            Drawable d = getDrawable();
            if (d == null)
                return;
            int width = getWidth();
            int height = getHeight();
            Log.e(TAG, "viewW:" + width + " ,viewH:" + height);
            // 拿到图片的宽和高
            int dw = d.getIntrinsicWidth();
            int dh = d.getIntrinsicHeight();
            Log.e(TAG, "imgW:" + dw + " ,imgH:" + dh);
            float scale = 1.0f;
            // 如果图片的宽或者高大于屏幕，则缩放至屏幕的宽或者高
            if (dw > width && dh <= height) {
                scale = width * 1.0f / dw;
                DrawableWidthBiggerThanHeight = true;
            }else if (dh > height && dw <= width) {
                scale = height * 1.0f / dh;
                DrawableWidthBiggerThanHeight = false;
            }else if (dw > width && dh > height) {
                scale = Math.min(dw * 1.0f / width, dh * 1.0f / height);
            }else if (dw < width && dh < height){
                scale = Math.min(width / dw * 1.0f, height / dh * 1.0f);
            }
            Log.d(TAG, "onGlobalLayout: scale="+scale);
            // 图片移动至屏幕中心
            centerPoint = new Point(width / 2, height / 2);
            mMatrix.setScale(scale, scale, centerPoint.getX(), centerPoint.getY());
            setImageMatrix(mMatrix);
            once = false;
        }

    }

    /**
     * 在缩放时，进行图片显示范围的控制
     */
    private void checkBorderAndCenterWhenScale() {
        RectF rect = getMatrixRectF();
        float deltaX = 0;
        float deltaY = 0;
        int width = getWidth();
        int height = getHeight();
        // 如果宽或高大于屏幕，则控制范围
        if (rect.width() >= width) {
            if (rect.left > 0) {
                deltaX = -rect.left;
            }
            if (rect.right < width) {
                deltaX = width - rect.right;
            }
        }
        if (rect.height() >= height) {
            if (rect.top > 0) {
                deltaY = -rect.top;
            }
            if (rect.bottom < height) {
                deltaY = height - rect.bottom;
            }
        }
        // 如果宽或高小于屏幕，则让其居中
        if (rect.width() < width) {
            deltaX = width * 0.5f - rect.right + 0.5f * rect.width();
        }
        if (rect.height() < height) {
            deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();
        }
//        Log.e(TAG, "deltaX = " + deltaX + " , deltaY = " + deltaY);
        mMatrix.postTranslate(deltaX, deltaY);
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        private final static String TAG = "ScaleListener";

        private float scale;
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            super.onScale(detector);
            scale = getScale();
            mScaleFactor = detector.getScaleFactor();
//            mScaleFactor *= detector.getScaleFactor();
//            Log.d(TAG, "onScale: scale=" + scale);
//            Log.d(TAG, "onScale: mScaleFactor=" + mScaleFactor);

            if (getDrawable() == null)
                return true;

            //缩放的范围控制
//            mScaleFactor = Math.max(SCALE_MIN, Math.min(mScaleFactor, SCALE_MAX));
            mFocusX = detector.getFocusX();
            mFocusY = detector.getFocusY();
            if ((scale < SCALE_MAX && mScaleFactor > 1.0f)
                    || (scale > SCALE_MIN && mScaleFactor < 1.0f)) {
            //最大值最小值判断
                if (mScaleFactor * scale < SCALE_MIN) {
                    mScaleFactor = SCALE_MIN / scale;
                }
                if (mScaleFactor * scale > SCALE_MAX) {
                    mScaleFactor = SCALE_MAX / scale;
                }
            //设置缩放比例
                mMatrix.postScale(mScaleFactor, mScaleFactor,
                        mFocusX, mFocusY);
//                checkBorderAndCenterWhenScale();
                setImageMatrix(mMatrix);
            }
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            super.onScaleEnd(detector);
            reBoundToInitScale(detector);
        }

        private void reBoundToInitScale(ScaleGestureDetector detector) {
            scale = getScale();
//            Log.d(TAG, "reBoundToInitScale: scale="+scale);
            mScaleFactor = detector.getScaleFactor();
//            Log.d(TAG, "reBoundToInitScale: scaleFactor"+mScaleFactor);
            if (getDrawable() == null) return ;
            if (scale < initScale){
                ZoomImageView.this.postDelayed(
                    new AutoScaleRunnable (initScale, detector.getCurrentSpanX(), detector.getCurrentSpanY()), 16);
            }
        }

    }
/*
    private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener {
        private PointF mFocusDelta;
        @Override
        public boolean onMove(MoveGestureDetector detector) {
            PointF mFocusDelta = detector.getFocusDelta();
            float scale = getScale();
            int mFocusX = getWidth();
            int mFocusY = getHeight();
            float scaledImageCenterX = (mFocusX*scale)/2;
            float scaledImageCenterY = (mFocusY*scale)/2;
            mFocusX += mFocusDelta.x;
            mFocusY += mFocusDelta.y;
            mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY);
            return true;
        }

    }*/

    /**
     * 自动缩放的任务
     *
     * @author zhy
     *
     */
    private class AutoScaleRunnable implements Runnable
    {
        static final float BIGGER = 1.07f;
        static final float SMALLER = 0.50f;
        private float mTargetScale;
        private float tmpScale;

        /**
         * 缩放的中心
         */
        private float x;
        private float y;

        /**
         * 传入目标缩放值，根据目标值与当前值，判断应该放大还是缩小
         *
         * @param targetScale
         */
        public AutoScaleRunnable(float targetScale, float x, float y)
        {
            this.mTargetScale = targetScale;
            this.x = x;
            this.y = y;
            if (getScale() < mTargetScale)
            {
                tmpScale = BIGGER;
            } else
            {
                tmpScale = SMALLER;
            }

        }

        @Override
        public void run()
        {
            // 进行缩放
            mMatrix.postScale(tmpScale, tmpScale, x, y);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mMatrix);
            final float currentScale = getScale();
//            Log.d(TAG, "run: currentScale="+currentScale);
            // 如果值在合法范围内，继续缩放
            if (((tmpScale >= 1f) && (currentScale < mTargetScale))
                    || ((tmpScale <= 1f) && (mTargetScale < currentScale))) {
                ZoomImageView.this.postDelayed(this, 16);
            } else{
            // 设置为目标的缩放比例
                final float deltaScale = mTargetScale / currentScale;
                mMatrix.postScale(deltaScale, deltaScale, x, y);
                checkBorderAndCenterWhenScale();
                setImageMatrix(mMatrix);
//                isAutoScale = false;
            }

        }
    }

}

